package org.hackystat.storageservice.resources.alt;

import org.hackystat.storageservice.db.derby.DerbyFacade;
import org.restlet.Context;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.resource.Representation;
import org.restlet.resource.Resource;
import org.restlet.resource.Variant;

import java.util.Map;

/**
 * The resource for processing GET/PUT/DELETE host/projects/{email}/{projectname}.
 * Returns a representation of the Project resource associated with this user.
 */
public class UserProjectResource extends Resource {
    private DerbyFacade db;
    private Util util;

    /**
     * Provides the following representational variants: TEXT_XML.
     *
     * @param context  The context.
     * @param request  The request object.
     * @param response The response object.
     */
    public UserProjectResource(Context context, Request request, Response response) {
        super(context, request, response);
        this.util = new Util(request, response);
        db = (DerbyFacade) getContext().getAttributes().get("DerbyFacade");
        getVariants().clear();
        getVariants().add(new Variant(MediaType.TEXT_XML));

    }

    /**
     * Returns an XML representation of the Project associated with this User.
     * <ul>
     * <li> The uriUser must be defined as a User.
     * <li> The Project must be defined for this User.
     * <li> The authenticated user must be the admin, or uriUser, or a member of the project, or
     * invited to be in the Project, or a spectator.
     * </ul>
     *
     * @param variant The representational variant requested, or null if conditions are violated.
     * @return The representation.
     */
    @Override
    public Representation represent(Variant variant) {
        // It's all good, so return the Project representation.
        if (variant.getMediaType().equals(MediaType.TEXT_XML)) {
            try {
                String ownerEmail = (String) getRequest().getAttributes().get("user");
                String projectName = (String) getRequest().getAttributes().get("projectname");
                String xmlData = db.getProject(ownerEmail, projectName);
                return Util.getStringRepresentation(xmlData);
            }
            catch (Exception e) {
                util.setStatusInternalError(e);
            }
        }
        return null;
    }

    /**
     * Indicate the PUT method is supported.
     *
     * @return True.
     */
    @Override
    public boolean allowPut() {
        return true;
    }

    /**
     * Implement the PUT method that creates a new Project or updates an existing Project.
     * <ul>
     * <li> The XML must be marshallable into a Project instance using the Project XmlSchema.
     * <li> The User must exist.
     * <li> The project representation must include a name, owner, start time, and end time.
     * <li> The Project name in the URI string must match the Project name in the XML.
     * <li> The authenticated user must be the uriUser or the admin.
     * <li> The project cannot be the Default project.
     * <li> All members in the new project representation must have been members previously.
     * <li> All Members, Invitees, and Spectators must be defined Users.
     * <li> The project owner cannot be a Member or Invitee or Spectator.
     * <li> No Invitee can be a Member or Spectator.
     * <li> No Spectator can be a Member or Invitee.
     * <li> If no UriPatterns are supplied, then the '*' UriPattern is provided by default.
     * </ul>
     *
     * @param entity The XML representation of the new Project.
     */
    @Override
    public void storeRepresentation(Representation entity) {
        String ownerEmail = (String) getRequest().getAttributes().get("user");
        String projectName = (String) getRequest().getAttributes().get("projectname");

        Form form = new Form(entity);
        Map<String, String> fields = form.getValuesMap();
        String startTime = fields.get("startTime");
        String endTime = fields.get("endTime");
        String lastMod = fields.get("lastMod");
        String xmlProject = fields.get("xmlProject");
        String xmlProjectRef = fields.get("xmlProjectRef");

        db.storeProject(ownerEmail, projectName, startTime, endTime, lastMod, xmlProject, xmlProjectRef);
        getResponse().setStatus(Status.SUCCESS_CREATED);
    }

    /**
     * Indicate the DELETE method is supported.
     *
     * @return True.
     */
    @Override
    public boolean allowDelete() {
        return true;
    }

    /**
     * Implement the DELETE method that deletes an existing Project for a given User.
     * <ul>
     * <li> The User must be currently defined.
     * <li> The authenticated user must be the uriUser or the Admin.
     * <li> The User must be the admin or the Owner.
     * <li> The project name must not be "Default".
     * </ul>
     * If the Project doesn't exist, that's fine, it's still "deleted".
     */
    @Override
    public void removeRepresentations() {
        try {
            String ownerEmail = (String) getRequest().getAttributes().get("user");
            String projectName = (String) getRequest().getAttributes().get("projectname");
            db.deleteProject(ownerEmail, projectName);
            getResponse().setStatus(Status.SUCCESS_OK);
        }
        catch (Exception e) {
            util.setStatusInternalError(e);
        }
    }
}
